package com.xx.springboot.config;

import com.baomidou.mybatisplus.extension.api.IErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.xx.springboot.entity.ResponseBo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 通用 Api Controller 全局异常处理
 * </p>
 * @author atom.hu
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * <p>
     * 自定义 REST 业务异常
     * <p>
     *
     * @param e 异常类型
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseBo handleBadRequest(Exception e) {
        /*
         * 业务逻辑异常
         */
        if (e instanceof ApiException) {
            IErrorCode errorCode = ((ApiException) e).getErrorCode();
            if (null != errorCode) {
                logger.debug("Rest request error, {}", errorCode.toString());
                return ResponseBo.error(e.getMessage());
            }
            logger.debug("Rest request error, {}", e.getMessage());
            return ResponseBo.error(e.getMessage());
        }

        /*
         * 参数校验异常
         */
        if (e instanceof BindException) {
           return handleBindException(e);
        }

        /**
         * 系统内部异常，打印异常栈
         */
        logger.error("Error: handleBadRequest StackTrace : {}", e);
        return ResponseBo.error(e.getMessage());
    }

    private ResponseBo handleBindException(Exception e) {
        BindingResult bindingResult = ((BindException) e).getBindingResult();
        if (null != bindingResult && bindingResult.hasErrors()) {
            List<Map<String, Object>> resList = new ArrayList<>();
            bindingResult.getFieldErrors().stream().forEach(err -> {
                Map<String, Object> obj = new HashMap<>();
                obj.put("name", err.getField());
                obj.put("msg", err.getDefaultMessage());
                resList.add(obj);
            });
            return ResponseBo.error(ResponseBo.BIND_EXCEPTION_CODE, (resList.get(0)).get("msg"));
        }
        return ResponseBo.error(e.getMessage());
    }
}
